## [unix(7)](https://ru.manpages.org/unix/7)

ПРИМЕР
В следующем коде демонстрируется использование пакето-упорядочивающих сокетов для локального межпроцессного обмена. Он состоит из двух программ. Программа-сервер ждёт подключения программы-клиента. Клиент посылает свой каждый аргумент командной строки в виде отдельного сообщения. Сервер считает входящие сообщения как целые числа и складывает их. Клиент посылает строку-команду «END». Сервер посылает ответное сообщение, содержащее сумму чисел клиента. Клиент печатает сумму и завершает работу. Сервер ждёт подключение следующего клиента. Для остановки сервера, клиент вызывается с аргументом командной строки «DOWN».
Следующий вывод был записан при работе сервера в фоновом режиме и повторяющемся запуске клиента. Выполнение программы-сервера завершилось после получения им команды «DOWN».

    Пример вывода
    $ ./server &
    [1] 25887
    $ ./client 3 4
    Результат = 7
    $ ./client 11 -5
    Результат = 6
    $ ./client DOWN
    Результат = 0
    [1]+  Done                    ./server
    $
    Исходный код программы
    /*
    * Файл connection.h
    */
    #define SOCKET_NAME "/tmp/9Lq7BNBnBycd6nxy.socket"
    #define BUFFER_SIZE 12
    /*
    * Файл server.c
    */
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/socket.h>
    #include <sys/un.h>
    #include <unistd.h>
    #include "connection.h"
    int
    main(int argc, char *argv[])
    {
        struct sockaddr_un name;
        int down_flag = 0;
        int ret;
        int connection_socket;
        int data_socket;
        int result;
        char buffer[BUFFER_SIZE];
        /*
        * Удалить сокет, оставшийся после последнего
        * некорректного завершения программы.
        */
        unlink(SOCKET_NAME);
        /* Создание локального сокета. */
        connection_socket = socket(AF_UNIX, SOCK_SEQPACKET, 0);
        if (connection_socket == -1) {
            perror("socket");
            exit(EXIT_FAILURE);
        }
        /*
        * Для переносимости очищаем всю структуру, так как в некоторых
        * реализациях имеются дополнительные (нестандартные) поля.
        */
        memset(&name, 0, sizeof(struct sockaddr_un));
        /* Привязываем сокет к имени сокета. */
        name.sun_family = AF_UNIX;
        strncpy(name.sun_path, SOCKET_NAME, sizeof(name.sun_path) - 1);
        ret = bind(connection_socket, (const struct sockaddr *) &name,
                sizeof(struct sockaddr_un));
        if (ret == -1) {
            perror("bind");
            exit(EXIT_FAILURE);
        }
        /*
        * Готовимся принимать подключения. Размер очереди (backlog)
        * устанавливаем равным 20. Пока один запрос обрабатывается, другие
        * запросы смогут подождать.
        */
        ret = listen(connection_socket, 20);
        if (ret == -1) {
            perror("listen");
            exit(EXIT_FAILURE);
        }
        /* Основной цикл обработки подключений. */
        for (;;) {
            /* Ожидание входящих подключений. */
            data_socket = accept(connection_socket, NULL, NULL);
            if (ret == -1) {
                perror("accept");
                exit(EXIT_FAILURE);
            }
            result = 0;
            for(;;) {
                /* Ожидание следующего пакета с данными. */
                ret = read(data_socket, buffer, BUFFER_SIZE);
                if (ret == -1) {
                    perror("read");
                    exit(EXIT_FAILURE);
                }
                /* Проверяем, что буфер завершается 0. */
                buffer[BUFFER_SIZE - 1] = 0;
                /* Обработка команд. */
                if (!strncmp(buffer, "DOWN", BUFFER_SIZE)) {
                    down_flag = 1;
                    break;
                }
                if (!strncmp(buffer, "END", BUFFER_SIZE)) {
                    break;
                }
                /* Добавляем полученную команду. */
                result += atoi(buffer);
            }
            /* Отправка результата. */
            sprintf(buffer, "%d", result);
            ret = write(data_socket, buffer, BUFFER_SIZE);
            if (ret == -1) {
                perror("write");
                exit(EXIT_FAILURE);
            }
            /* Закрытие сокета. */
            close(data_socket);
            /* Завершаем работу по команде DOWN. */
            if (down_flag) {
                break;
            }
        }
        close(connection_socket);
        /* Удаляем сокет. */
        unlink(SOCKET_NAME);
        exit(EXIT_SUCCESS);
    }
    /*
    * Файл client.c
    */
    #include <errno.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/socket.h>
    #include <sys/un.h>
    #include <unistd.h>
    #include "connection.h"
    int
    main(int argc, char *argv[])
    {
        struct sockaddr_un name;
        int i;
        int ret;
        int data_socket;
        char buffer[BUFFER_SIZE];
        /* Создание локального сокета. */
        data_socket = socket(AF_UNIX, SOCK_SEQPACKET, 0);
        if (data_socket == -1) {
            perror("socket");
            exit(EXIT_FAILURE);
        }
        /*
        * Для переносимости очищаем всю структуру, так как в некоторых
        * реализациях имеются дополнительные (нестандартные) поля.
        */
        memset(&name, 0, sizeof(struct sockaddr_un));
        /* Соединяем сокет с именем сокета. */
        name.sun_family = AF_UNIX;
        strncpy(name.sun_path, SOCKET_NAME, sizeof(name.sun_path) - 1);
        ret = connect (data_socket, (const struct sockaddr *) &name,
                    sizeof(struct sockaddr_un));
        if (ret == -1) {
            fprintf(stderr, "Сервер выключен.\n");
            exit(EXIT_FAILURE);
        }
        /* Посылаем аргументы. */
        for (i = 1; i < argc; ++i) {
            ret = write(data_socket, argv[i], strlen(argv[i]) + 1);
            if (ret == -1) {
                perror("write");
                break;
            }
        }
        /* Отправка результата. */
        strcpy (buffer, "END");
        ret = write(data_socket, buffer, strlen(buffer) + 1);
        if (ret == -1) {
            perror("write");
            exit(EXIT_FAILURE);
        }
        /* Получение результата. */
        ret = read(data_socket, buffer, BUFFER_SIZE);
        if (ret == -1) {
            perror("read");
            exit(EXIT_FAILURE);
        }
        /* Проверяем, что буфер завершается 0. */
        buffer[BUFFER_SIZE - 1] = 0;
        printf("Result = %s\n", buffer);
        /* Закрытие сокета. */
        close(data_socket);
        exit(EXIT_SUCCESS);
    }
Пример использования SCM_RIGHTS приведён в cmsg(3).